﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Cci;
using Microsoft.Cci.MutableCodeModel;
using Microsoft.Cci.Contracts;


namespace Mutator
{
    class Mutants : Microsoft.Cci.MutableCodeModel.CodeMutator
    {
        public static bool mutated = false;
        public static HashSet<int> toVisit = new HashSet<int>();
        public static int mutantNumber = 0;

        public ExpressionMutantGenerator expressionMutantGenerator;

        public ConditionMutantGenerator conditionMutantGenerator;


        public Mutants(IMetadataHost host)
            : base(host)
        {

        }
        public Mutants(IMetadataHost host, ISourceLocationProvider/*?*/ sourceLocationProvider)
            : base(host, sourceLocationProvider)
        {

        }

        // Bug fixed: we should not move the local variable declaration to a inner block.
        /*public override IStatement Visit(LocalDeclarationStatement localDeclarationStatement)
        {

            if (doMutate)
            {
                BlockStatement wholeBlock = this.generateExpressionMutants(localDeclarationStatement);
                wholeBlock.Statements.Add(localDeclarationStatement);
                doMutate = false;
                IBlockStatement returnBlock = this.Visit(wholeBlock);
                doMutate = true;
                return returnBlock;
            }
            else
            {
                localDeclarationStatement.LocalVariable = this.Visit(this.GetMutableCopy(localDeclarationStatement.LocalVariable));
                if (localDeclarationStatement.InitialValue != null)
                    localDeclarationStatement.InitialValue = Visit(localDeclarationStatement.InitialValue);
                return localDeclarationStatement;
            }

        }*/

        public override IStatement Visit(ReturnStatement returnStatement)
        {
            if (returnStatement.Expression != null)
            {
                returnStatement.Expression = expressionMutantGenerator.Visit(returnStatement.Expression);
                returnStatement.Expression = base.Visit(returnStatement.Expression);
            }

            return returnStatement;
        }
        public override IStatement Visit(ExpressionStatement expressionStatement)
        {
            expressionStatement.Expression = expressionMutantGenerator.Visit(expressionStatement.Expression);
            expressionStatement.Expression=base.Visit(expressionStatement.Expression);
            return expressionStatement;
        }
        public override IStatement Visit(WhileDoStatement whileDoStatement)
        {

            whileDoStatement.Condition = conditionMutantGenerator.Visit(whileDoStatement.Condition);
            whileDoStatement.Condition = base.Visit(whileDoStatement.Condition);
            whileDoStatement.Body = Visit(whileDoStatement.Body);
            return whileDoStatement;

        }
        public override IStatement Visit(ForStatement forStatement)
        {
            forStatement.InitStatements = Visit(forStatement.InitStatements);
            forStatement.Condition = conditionMutantGenerator.Visit(forStatement.Condition);
            forStatement.Condition = base.Visit(forStatement.Condition);
            forStatement.IncrementStatements = Visit(forStatement.IncrementStatements);
            forStatement.Body = Visit(forStatement.Body);
            return forStatement;

        }
        public override IStatement Visit(ConditionalStatement conditionalStatement)
        {

            conditionalStatement.Condition = conditionMutantGenerator.Visit(conditionalStatement.Condition);
            conditionalStatement.Condition = base.Visit(conditionalStatement.Condition);
            conditionalStatement.TrueBranch = Visit(conditionalStatement.TrueBranch);
            conditionalStatement.FalseBranch = Visit(conditionalStatement.FalseBranch);

            return conditionalStatement;

        }


    }


}
